package org.qloudgen.txn.dilithium.cluster.pages;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Check;
import org.apache.wicket.markup.html.form.CheckGroup;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.RadioChoice;
import org.apache.wicket.markup.html.form.RequiredTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.PageableListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.validation.validator.RangeValidator;

import org.qloudgen.txn.dilithium.cluster.pages.common.BasePage;
import org.qloudgen.txn.dilithium.cluster.beans.Cluster;
import org.qloudgen.txn.dilithium.cluster.beans.ParameterBean;
import org.qloudgen.txn.dilithium.cluster.common.CommonValues;
import org.qloudgen.txn.dilithium.cluster.common.ShellExec;
import org.qloudgen.txn.dilithium.cluster.database.ClusterImpl;

public class CreateClusterPage extends BasePage{
	
	/**
	 * @Author youngeryoyo
	 * youngeryoyo@gmail.com
	 */
	static Log log = LogFactory.getLog(CreateClusterPage.class);
	
	private static final long serialVersionUID = 1L;
	private transient Cluster cluster;
	private transient List<ParameterBean> paramList ;
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public CreateClusterPage(PageParameters pageParameters){
		super();
		
		this.pp = pageParameters;
		
		// form.border
		final WebMarkupContainer border = new WebMarkupContainer("border");
		border.setDefaultModel(new CompoundPropertyModel<Cluster>(new Cluster()));
				
		// form.paramBorder
		final WebMarkupContainer paramBorder = new WebMarkupContainer("paramBorder");
		paramBorder.setOutputMarkupId(true);
		
		// form.paramBorder.paramGroup
		final CheckGroup<ParameterBean> paramGroup = new CheckGroup<ParameterBean>("paramGroup", new ArrayList<ParameterBean>());
		paramGroup.setRenderBodyOnly(false).setOutputMarkupId(true).setVisible(false);
		paramBorder.add(paramGroup);
		
		// feedback
		final FeedbackPanel feedback = new FeedbackPanel("feedback");
		feedback.setOutputMarkupId(true);
		this.add(feedback);
	
		// form
		final Form form = new Form("form") {
			
			private static final long serialVersionUID = 1L;
			protected void onSubmit() {
				cluster = (Cluster)border.getDefaultModelObject();
				List<ParameterBean> parameterList = (List<ParameterBean>) (paramGroup.getModelObject());

				cluster.setUserNo(pp.get("userNo").toString());
				cluster.setSysUser(CommonValues.SYSUSER);
				
				if (cluster.getDBSuperuserPassword() == null) cluster.setDBSuperuserPassword(CommonValues.DEFAULT_DB_SUPERUSER_PASSWORD);
				
				if (cluster.getRadioChoice() == null) cluster.setRadioChoice("default");
				
				if (!cluster.getRadioChoice().equals("default")){
					if (parameterList.size() != paramList.size()) { info(CommonValues.ERROR_PARAMETER_LENGTH); return;}
				}
				
				// check cluster info 
				String checkInfo = cluster.checkClusterInfo();
				
				if (checkInfo != null && !checkInfo.equals("")) { info(checkInfo);
				} else {
					
					cluster.setClusterID(ClusterImpl.getClusterID() );
					
					if (CommonValues.CONSTRUCT_NO_PASS) {
						// copy local ssh key to controller ip in order to ssh controllerip from web app server
						int ret = ShellExec.copySSHKey("local",null,cluster.getControllerIp(),cluster.getSysUser(),cluster.getSysUserPassword());
					    if (ret != 0) {
					    	error(CommonValues.ERROR_COPYSSH_KEY);
					    	return;
					    }
					    
						// scp copySSHKey.sh to controller node
						ret = ShellExec.scpFile(cluster,CommonValues.COPY_SSHKEY_SH,CommonValues.COPYSSHKEY_FILE);
						if (ret != 0) {
							error(CommonValues.ERROR_SCP_FILE);
					    	return;
						}
					}
					// save meta data to metadb
					ClusterImpl.createCluster(cluster,parameterList);
					setResponsePage(ClusterMainPage.class,pp);
				
				}
			}
			
		};
		this.add(form);
		form.add(border);
		form.add(paramBorder);
		
		// form.border.(clusterName,clusterDesc,controllerIp,sysUserPassword,rootPassword)
		border.add(new RequiredTextField<String>("clusterName"));
		border.add(new TextField<String>("clusterDesc"));
		border.add(new RequiredTextField<String>("controllerIp"));
		border.add(new PasswordTextField("sysUserPassword").setRequired(true));
		border.add(new TextField("DBSuperuserPassword"));
		
		// form.border.radioChoice
		final RadioChoice radioChoice = new RadioChoice("radioChoice",CommonValues.configTypes,
				new	ChoiceRenderer() {
					private static final long serialVersionUID = 1L;
					public Object getDisplayValue(Object object) {
						return CommonValues.configTypeNames.get(object);
					}
				}).setSuffix("");
		radioChoice.add(new AjaxFormChoiceComponentUpdatingBehavior() {
		    private static final long serialVersionUID = 1L;          
		    protected void onUpdate(AjaxRequestTarget target) {  
	                   String configChoice = (String) radioChoice.getModelObject();
	                   if (configChoice != null) {
		                   if (configChoice.equals("default")){
		                	   paramGroup.setVisible(false);
		                   } else {
		                	   paramGroup.setVisible(true);
		                   }
	                   }
	                   target.add(paramBorder);
		    }
		});
		border.add(radioChoice);
	
		//get default conf from metadb
		paramList = ClusterImpl.getDefaultConf();
		
		final PageableListView<ParameterBean> paramListView = new PageableListView<ParameterBean>( "tableRows", paramList,CommonValues.CLUSTER_CONF_PARAM_LIST) {
			
			private static final long serialVersionUID = 1L;
			protected void populateItem(ListItem<ParameterBean> item) {
				
				final ParameterBean param=(ParameterBean) item.getModelObject();
				item.add(new Check("tableCheck", item.getModel()){
					private static final long serialVersionUID = 1L;
					protected void onComponentTag(ComponentTag tag)
					{
						super.onComponentTag(tag);
						tag.put("checked", true);
					}}.setEnabled(true));
				item.add(new Label( "paramType", param.getParamType()));
				item.add(new Label( "chnName", param.getChnName()));
				
				final TextField keyValue = new TextField("paramValue");
				keyValue.setType(Integer.class);
				
				keyValue.add(new AjaxFormComponentUpdatingBehavior("onChange") {
	    	  		
	    	  		private static final long serialVersionUID = 1L;
					@Override
					protected void onUpdate(AjaxRequestTarget target) {
						param.setParamValue( (Integer) keyValue.getModelObject());
		    	  	}
	    	  	});
				keyValue.setModel(new CompoundPropertyModel(new Integer(1)));
				keyValue.setModelObject(param.getParamValue());
				
				RangeValidator<Integer> range = new RangeValidator<Integer>(param.getMinValue(),param.getMaxValue());
				keyValue.add(range);
				item.add( keyValue);
				
			}
		};

		paramListView.setOutputMarkupId(true);
		paramGroup.add(paramListView);
		
		form.add(new Button ("submit"));
		
		Button cancel = new Button ("cancel"){
			private static final long serialVersionUID = 1L;
			public void onSubmit() {
				setResponsePage(ClusterMainPage.class,pp);
			}
		};
		form.add(cancel);
		cancel.setDefaultFormProcessing(false);
		
		addFooter();
		
	}

}
